#include "main.h"

ues_core_api_t ues_pub_c_api;
ues_api_t *api;
void *env;

struct test_s
{
	int num1;
	int num2;
	char *string1;
	float flt1;
};

// Print hook
int printfya(char *str, ...)
{
	va_list args;
	unsigned char buff[0x4000];
	va_start(args,str);
	vsprintf(buff,str,args);
	va_end(args);
	printf(buff);
	return 1;
}

// Print something
int		print(char *str)
{
	printf(str);
	return 1;
}

// Makes something to string
char*		tostring(int num)
{
	char blub[0xFFFF];
	char *news;
	sprintf(blub, "%i", num);
	news=malloc(strlen(blub)+1);
	memcpy(news, blub, strlen(blub)+1);
	return news;
}

char blub[0xFFFF];

// Float to string
char*		ftos(float flt)
{
	sprintf(blub, "%f", flt);
	return blub;
}

// Int to float
float		itof(int num)
{
	return (float)num;
}

// Float to int
int			ftoi(float num)
{
	return (int)num;
}

// "getVersion" dummy
char*	getVersion(int type)
{
	return "this is a C language call";
}

// Load other file
int		load(char *file)
{
	api->Load(file, env);
	return 1;
}

void	sigill(int i)
{
	printf("%i",i);
	system("PAUSE");
}
float a=1.2f;
float b=1.7f;
float d=6.1f;
float e=1.1f;

float	makefloat()
{
	return 1.5f;
}

int		strrcv(struct test_s *pStruct)
{
	printf(pStruct->string1);
	return 1;
}

struct test_s snd;
struct test_s*	strsnd(int num2)
{
	snd.flt1=1.669f;
	snd.num1=5;
	snd.num2=num2;
	snd.string1="sndstr1122";
	return &snd;
}

typedef struct vec3_s
{
	float x;
	float y;
	float z;
} vec3_t;

void	UES_OnMemoryExecAlloc(void *pMem, size_t sSize)
{
	DWORD oldprot;
	if (!VirtualProtect (pMem, sSize, PAGE_EXECUTE_READWRITE, &oldprot))
	{
		printf("Failed to change protection\n");
		exit(EXIT_FAILURE);
	}
}

vec3_t _tmp;
vec3_t*	gettest()
{
	_tmp.x=122;
	_tmp.y=2142;
	_tmp.z=698;
	return &_tmp;
}

// Blub
int		main(int argc, char *argv[])
{
	// Init environment and run the file
	void (*c)();
	clock_t then=clock();
	HANDLE pFile;
	long size;

	pFile = CreateFile("filesizetest.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	size = GetFileSize(pFile, NULL);

	signal(SIGINT,sigill);

	ues_pub_c_api.Print=printfya;
	ues_pub_c_api.OnMemoryExecAlloc=UES_OnMemoryExecAlloc;
	api=UESLoadAPI(&ues_pub_c_api);

	env=api->CreateEnv();
	api->CreateStruct(env, "test_s", 4, UES_CAST_INT, "num1", UES_CAST_INT, "num2", UES_CAST_STRING, "string1", UES_CAST_FLOAT, "flt1");
	api->InitFunction(print, "print", env, UES_CAST_INT, FALSE, NULL, api->CreateArgArea(1, UES_CAST_STRING));
	api->InitFunction(tostring, "tostring", env, UES_CAST_STRING, FALSE, NULL, api->CreateArgArea(1, UES_CAST_INT));
	api->InitFunction(load, "load", env, UES_CAST_INT, FALSE, NULL, api->CreateArgArea(1, UES_CAST_STRING));
	api->InitFunction(getVersion, "getVersionDummy", env, UES_CAST_STRING, FALSE, NULL, api->CreateArgArea(1, UES_CAST_INT));
	api->InitFunction(ftos, "ftos", env, UES_CAST_STRING, FALSE, NULL, api->CreateArgArea(1, UES_CAST_FLOAT));
	api->InitFunction(itof, "itof", env, UES_CAST_FLOAT, FALSE, NULL, api->CreateArgArea(1, UES_CAST_INT));
	api->InitFunction(ftoi, "ftoi", env, UES_CAST_INT, FALSE, NULL, api->CreateArgArea(1, UES_CAST_FLOAT));
	api->InitFunction(makefloat, "giveFloat", env, UES_CAST_FLOAT, FALSE, NULL, api->CreateArgArea(0));
	api->InitFunction(strrcv, "giveStruct", env, UES_CAST_INT, FALSE, NULL, api->CreateArgArea(1, UES_CAST_STRUCT, api->GetStructByName(env, "test_s")));
	api->InitFunction(strsnd, "sendStruct", env, UES_CAST_STRUCT, api->GetStructByName(env, "test_s"), NULL, api->CreateArgArea(0));
	api->CreateSingleDef(env, "_int", UES_CAST_INT);
	api->CreateSingleDef(env, "_string", UES_CAST_STRING);
	api->CreateStruct(env, "object", 1, UES_CAST_PTR, "ptr");
	api->CreateStruct(env, "vec3", 3, UES_CAST_FLOAT, "x", UES_CAST_FLOAT, "y", UES_CAST_FLOAT, "z");
	api->InitFunction(gettest, "gettest", env, UES_CAST_STRUCT, api->GetStructByName(env,"vec3"), NULL, api->CreateArgArea(0));

	c=api->Load("init.ues", env);
	__try
	{
		if (c)
			c();
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		printf("Error\n");
	}
	printf("* Executed in %ums\n", clock()-then);
	api->FreeEnvironment(env);
#ifdef _DEBUG
	api->PrintMemoryUsage();
#endif
	getchar();
	return EXIT_SUCCESS;
}